'''
    Initialization of data import
    Import the data in the sqlite database into the mysql database
'''
import yaml
import os
import sqlite3
from libs.dbutils.mysql_helper import MySqlHelper
from libs.dbutils.sqlalchemy_helper import DBHelper


class InitDataBase():
    '''
    functional description:
        Database initialization, generate multiple databases and data based on configuration files
     modify record:
    '''

    def __init__(self, config_file_path=None, *args, **Kwargs):
        '''
        functional description:
        parameter:
            config_file_path:The path of the configuration file that needs to initialize the database in the project
        return value:
        exception description:
        modify record:
        '''

        self.config_file_path = config_file_path
        # yaml配置文件内容
        self.config_file_datas = self.__read_config_file()

        self.src_package_data = None

        self.bin_package_data = None

    def init_data(self):
        '''
        functional description:Initialization of the database
        parameter:
        return value:
        exception description:
        modify record:
        '''

        if self.__exists_repeat_database():
            return 'duplicate database name'

        for database in self.config_file_datas:
            # Initialization data
            self._init_data(database)

    def _init_data(self, database):
        '''
        functional description:data initialization operation
        parameter:
            database:database configuration information
        return value:
        exception description:
        modify record:
        '''
        # 1. create a database and related tables in the database

        # 2. get the data of binary packages and source packages
        self.get_package_data(database.get('src_db_file'),
                              database.get('bin_db_file'))

    def __exists_repeat_database(self):
        '''
        functional description:Determine if the same database name exists
        parameter:
        return value:
        exception description:
        modify record:
        '''
        db_names = [name.get('dbname')
                    for name in self.config_file_datas]

        if len(set(db_names)) != len(self.config_file_datas):
            return True

        return False

    def get_package_data(self, src_package_path, bin_package_path):
        '''
        functional description:Obtain the data of source package and binary package separately
        parameter:
            src_package_path:source package path
            bin_package_path:binary package path
        return value:
        exception description:
        modify record:
        '''
        if os.path.exists(src_package_path) is False:
            raise Exception('the sqlite file included source rpm info does not exist')
        self.src_package_data = self.__load_package_data(src_package_path)

        if os.path.exists(bin_package_path) is False:
            raise Exception('the sqlite file included binary rpm info does not exist')
        self.bin_package_data = self.__load_package_data(bin_package_path)

    def __load_package_data(self, db_file_path):
        '''
        functional description:Load package data from sqlite database
        parameter:
            db_file_path:database file path
        return value:
        exception description:
        modify record:
        '''
        return LoadSqliteDataBase(db_file_path).get_package_data()

    def __save_package_data(self):
        '''
        functional description:
        parameter:
        return value:
        exception description:
        modify record:
        '''
        pass

    def __read_config_file(self):
        '''
        functional description:Read the contents of the configuration file load each node data in the yaml configuration
                               file as a list to return
        parameter:
        return value:
        exception description:
        modify record:
        '''
        if self.config_file is None:
            return []

        # load yaml file
        with open(self.config_file, 'r', encoding='utf-8') as f:
            return yaml.load(f.read())

    def __updata_settings_file(self, **Kwargs):
        '''
        functional description:update some configuration files related to the database in the system
        parameter:
            **Kwargs：data related to configuration file nodes
            database_name: Name database
            priority: priority
        return value:
        exception description:
        modify record:
        '''

        pass


class LoadSqliteDataBase():
    '''
    functional description:
        Load data from sqlite database
    modify record:
    '''

    def __init__(self, db_file, *arg, **Kwargs):
        '''
        functional description:Initialize and load sqlite related database
        parameter:
            db_file：Database related files
        return value:
        exception description:
        modify record:
        '''

        self.db_file = db_file
        self.conn = sqlite3.connect(self.db_file)

    def close(self):
        '''
        functional description:Close the database connection
        parameter:
        return value:
        exception description:
        modify record:
        '''

        self.coon.close()

    def __columns(self, cursor):
        '''
        functional description:Returns all the column names queried by the current cursor
        parameter:
            cursor：Cursor object
        return value:
        exception description:
        modify record:
        '''

        return [col[0] for col in cursor.descriotion]

    def __get_src_package_data(self):
        '''
        functional description:Get the data in the source package
        parameter:
        return value:
        exception description:
        modify record:
        '''

        cursor = self.conn.execute(
            "SELECT pkgId,pkgKey,name,version,rpm_license,url from packages ")

        return [dict(zip(self.__columns(cursor), row)) for row in cursor.fetchall()]

    def __get_bin_package_data(self):
        '''
        functional description:Get binary package data
        parameter:
        return value:
        exception description:
        modify record:
        '''
        cursor = self.conn.execute(
            'SELECT pkgId,pkgKey,name,version,rpm_license,url from packages ')
        return [dict(zip(self.__columns(cursor), row)) for row in cursor.fetchall()]

    def get_package_data(self, source='src'):
        '''
        functional description:Get package data
        parameter:
            source： distinguish between source packages and binary packages
        return value:
        exception description:
        modify record:
        '''
        if source == 'src':
            return self.__get_src_package_data()

        return self.__get_bin_package_data()


class DatabaseOperations():
    '''
    functional description:Related to database operations, creating databases, creating tables
    modify record:
    '''

    def __init__(self, db_name):

        self.db_name = db_name

    def create_database(self):
        '''
        functional description:create a database
        parameter:
        return value:
        exception description:
        modify record:
        '''
        create_database_sql = '''
                                drop database if exists `{db_name}`;
                                create database `{db_name}` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
                            '''.format(db_name=self.db_name)
        with MySqlHelper(db_name='packagemanage') as db:
            # create database
            try:
                db.cursor.execute(create_database_sql)
            except Exception:
                return False
            else:
                # create all tables
                return self.__create_all_tables()

    def __create_all_tables(self):
        '''
        functional description:create all tables
        parameter:
        return value:
        exception description:
        modify record:
        '''
        try:
            DBHelper.create_all(self.db_name)
        except Exception:
            return False
        else:
            return True


if __name__ == "__main__":
    pass
    # creatadatabase = DatabaseOperations('test_db')
    # creatadatabase.create_database()

    # file_path = os.path.join(os.path.split(
    #     os.path.realpath(__file__))[0], 'testdb/src')
    # load_data = LoadSqliteDataBase(file_path)
    # src_package_datas = load_data.get_package_data()
    # print(src_package_datas)
